package com.xpq.petserver.service.impl;

import com.xpq.petserver.config.FilePathProperties;
import com.xpq.petserver.converter.UserConverter;
import com.xpq.petserver.entity.R;
import com.xpq.petserver.entity.dto.*;
import com.xpq.petserver.entity.po.User;
import com.xpq.petserver.entity.vo.UserInfoVO;
import com.xpq.petserver.exception.AppException;
import com.xpq.petserver.exception.AppExceptionCodeMsg;
import com.xpq.petserver.util.JwtUtil;
import com.xpq.petserver.util.TimeUtli;
import com.xpq.petserver.mapper.UserMapper;
import com.xpq.petserver.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;

/**
 * 用户表相关业务
 *
 * @author XPQ
 * @date 2022-04-01
 */
@Slf4j
@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private FilePathProperties filePathProperties;
    @Autowired
    private UserMapper userMapper;

    /**
     * 注册用户业务
     *
     * @param registerUserDTO 新用户信息
     * @return
     */
    @Override
    public R registerUser(RegisterUserDTO registerUserDTO) {
        // 生成账号、创建时间、修改时间
        registerUserDTO.setId("pet_" + System.currentTimeMillis());
        registerUserDTO.setCreateTime(TimeUtli.getCurrentTime());
        registerUserDTO.setUpdateTime(TimeUtli.getCurrentTime());
        // 密码前端后端双重md5加密
        registerUserDTO.setPassword(DigestUtils.md5DigestAsHex(registerUserDTO.getPassword().getBytes()));
        try {
            userMapper.createUser(registerUserDTO);
        } catch (DuplicateKeyException e) { // 重复主键异常
            throw new AppException(AppExceptionCodeMsg.ACCOUNT_REGISTERED);
        }
        return R.success("注册成功！");
    }

    /**
     * 用户登录服务
     *
     * @param loginDTO 用户登录信息
     * @return
     */
    public R login(LoginDTO loginDTO) {
        User user = userMapper.selectUserByPhone(loginDTO.getPhone());
        if (user == null) { // 用户不存在
            throw new AppException(AppExceptionCodeMsg.ACCOUNT_OR_PASSWORD_ERROR);
        }
        log.debug("用户登录信息：{}", loginDTO);
        log.debug("前端密码：{}", DigestUtils.md5DigestAsHex(loginDTO.getPassword().getBytes()));
        log.debug("数据库密码：{}", user.getPassword());
        // 用户存在且密码正确
        if ((DigestUtils.md5DigestAsHex(loginDTO.getPassword().getBytes())).equals(user.getPassword())) {
            String token = JwtUtil.getToken(user.getId()); // 加上用户相关信息生成token
            HashMap<String, String> map = new HashMap<>();
            map.put("token", token);
            map.put("avatarPath", filePathProperties.getAvatarLogicalPath() + user.getAvatar());
            return R.success("登录成功！", map);
        } else { // 密码错误
            throw new AppException(AppExceptionCodeMsg.ACCOUNT_OR_PASSWORD_ERROR);
        }
    }

    /**
     * 获取用户信息
     *
     * @param id 用户id
     * @return 用户头像地址
     */
    @Override
    public R getUserInfo(String id) {
        User user = userMapper.selectUserById(id);
        // 如果昵称为空则账号作为昵称
        user.setNickname(user.getNickname() == null ? user.getId() : user.getNickname());
        // 如果用户头像不为空，则返回完整的url地址
        user.setAvatar(user.getAvatar() == null ? null : (filePathProperties.getAvatarLogicalPath() + user.getAvatar()));
        UserInfoVO userInfoVO = UserConverter.INSTANCE.toUserInfoVO(user);
        return R.success(userInfoVO);
    }


    /**
     * 上传修改用户头像
     *
     * @param avatar 用户上传的头像文件
     * @param userId 用户的id
     * @return
     */
    @Override
    public R uploadAvatar(MultipartFile avatar, String userId) {
        User user = userMapper.selectUserById(userId);
        // 判断文件夹是否存在
        File fileDir = new File(filePathProperties.getAvatarPhysicalPath());
        if (!fileDir.exists()) {
            fileDir.mkdirs();
        }
        // 创建新文件保存头像
        String avatarName = System.currentTimeMillis() + avatar.getOriginalFilename();
        File file = new File(fileDir, avatarName);
        try {
            file.createNewFile();
            // 修改数据库并保存新头像到磁盘
            userMapper.updateAvatar(user.getId(), avatarName);
            avatar.transferTo(file);
            // 如果原来已经有头像，则删除原来的头像
            if (user.getAvatar() != null) {
                File oldFile = new File(
                        filePathProperties.getAvatarPhysicalPath()+ user.getAvatar());
                oldFile.delete();
            }
            // 将头像路径返回给前端
            HashMap<String, String> resData = new HashMap<>();
            resData.put("avatarPath", filePathProperties.getAvatarLogicalPath() + avatarName);
            return R.success("更换成功！", resData);
        } catch (IOException e) {
            e.printStackTrace();
            throw new AppException(AppExceptionCodeMsg.CHANGE_AVATAR_ERROR);
        }
    }

    /**
     * 修改用户基本信息
     *
     * @param userBasicInfoDTO 用户基本信息
     * @return
     */
    @Override
    public R updateUserBasicInfo(UserBasicInfoDTO userBasicInfoDTO) {
        userBasicInfoDTO.setUpdateTime(TimeUtli.getCurrentTime());
        userMapper.updateUserBasicInfo(userBasicInfoDTO);
        return R.success("保存成功！", null);
    }

    /**
     * 修改用户密码
     *
     * @param updatePasswordDTO 用户id和原、新密码
     * @return
     */
    @Override
    public R updatePassword(UpdatePasswordDTO updatePasswordDTO) {
        User user = userMapper.selectUserById(updatePasswordDTO.getId());
        // 判断密码是否正确
        if ((DigestUtils.md5DigestAsHex(updatePasswordDTO.getOriginalPassword().getBytes())).equals(user.getPassword())) {
            updatePasswordDTO.setNewPassword(DigestUtils.md5DigestAsHex(updatePasswordDTO.getNewPassword().getBytes()));
            updatePasswordDTO.setUpdateTime(TimeUtli.getCurrentTime());
            userMapper.updatePassword(updatePasswordDTO);
            return R.success("修改成功！", null);
        } else {
            throw new AppException(AppExceptionCodeMsg.PASSWORD_ERROR);
        }
    }

    /**
     * 修改用户手机号码
     *
     * @param updatePhoneDTO 用户id、新手机号、密码
     * @return
     */
    @Override
    public R updatePhone(UpdatePhoneDTO updatePhoneDTO) {
        User user = userMapper.selectUserById(updatePhoneDTO.getId());
        // 密码不正确
        if (!(DigestUtils.md5DigestAsHex(updatePhoneDTO.getPassword().getBytes())).equals(user.getPassword())) {
            throw new AppException(AppExceptionCodeMsg.PASSWORD_ERROR);
        }
        updatePhoneDTO.setUpdateTime(TimeUtli.getCurrentTime());
        try {
            userMapper.updatePhone(updatePhoneDTO);
            return R.success("修改成功！", null);
        } catch (DuplicateKeyException e) {
            e.printStackTrace();
            throw new AppException(AppExceptionCodeMsg.PHONE_REGISTERED);
        }
    }
}
